package com.hwtx.form.util;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class JsonRecursiveFinder {

    /**
     * 查找所有匹配字段名的节点及其路径信息
     */
    public static List<NodePathInfo> findNodesByFieldName(JsonNode root, String targetFieldName) {
        List<NodePathInfo> results = new ArrayList<>();
        findNodesRecursive(root, "", null, targetFieldName, null, results);
        return results;
    }

    /**
     * 查找所有包含特定值的节点及其路径信息
     */
    public static List<NodePathInfo> findNodesByValue(JsonNode root, String targetValue) {
        List<NodePathInfo> results = new ArrayList<>();
        findNodesRecursive(root, "", null, null, targetValue, results);
        return results;
    }

    /**
     * 使用自定义条件查找节点
     */
    public static List<NodePathInfo> findNodesWithCondition(JsonNode root, Predicate<JsonNode> condition) {
        List<NodePathInfo> results = new ArrayList<>();
        findNodesRecursive(root, "", null, null, null, results, condition);
        return results;
    }

    /**
     * 核心递归方法 - 按字段名或值查找
     */
    private static void findNodesRecursive(JsonNode currentNode, String currentPath, 
                                          JsonNode parentNode, String targetFieldName, 
                                          String targetValue, List<NodePathInfo> results) {
        
        // 检查当前节点是否匹配条件
        if (targetFieldName != null && parentNode != null && parentNode.isObject()) {
            // 如果是按字段名查找，需要检查父节点的字段名
            checkFieldNameMatch(currentNode, currentPath, parentNode, targetFieldName, results);
        } else if (targetValue != null && currentNode.isValueNode()) {
            // 如果是按值查找，检查当前节点的值
            checkValueMatch(currentNode, currentPath, parentNode, targetValue, results);
        }

        // 递归遍历子节点
        if (currentNode.isObject()) {
            traverseObject(currentNode, currentPath, results, targetFieldName, targetValue);
        } else if (currentNode.isArray()) {
            traverseArray(currentNode, currentPath, results, targetFieldName, targetValue);
        }
    }

    /**
     * 核心递归方法 - 使用自定义条件
     */
    private static void findNodesRecursive(JsonNode currentNode, String currentPath, 
                                          JsonNode parentNode, String targetFieldName, 
                                          String targetValue, List<NodePathInfo> results,
                                          Predicate<JsonNode> condition) {
        
        // 检查自定义条件
        if (condition.test(currentNode)) {
            results.add(new NodePathInfo(currentNode, currentPath, parentNode));
        }

        // 递归遍历子节点
        if (currentNode.isObject()) {
            traverseObject(currentNode, currentPath, results, targetFieldName, targetValue, condition);
        } else if (currentNode.isArray()) {
            traverseArray(currentNode, currentPath, results, targetFieldName, targetValue, condition);
        }
    }

    /**
     * 遍历JSON对象
     */
    private static void traverseObject(JsonNode objectNode, String currentPath, 
                                      List<NodePathInfo> results, String targetFieldName, 
                                      String targetValue) {
        
        Iterator<Map.Entry<String, JsonNode>> fields = objectNode.fields();
        while (fields.hasNext()) {
            Map.Entry<String, JsonNode> entry = fields.next();
            String fieldName = entry.getKey();
            JsonNode childNode = entry.getValue();
            String childPath = buildPath(currentPath, fieldName);

            // 递归调用
            findNodesRecursive(childNode, childPath, objectNode, targetFieldName, targetValue, results);
        }
    }

    /**
     * 遍历JSON数组
     */
    private static void traverseArray(JsonNode arrayNode, String currentPath, 
                                     List<NodePathInfo> results, String targetFieldName, 
                                     String targetValue) {
        
        for (int i = 0; i < arrayNode.size(); i++) {
            JsonNode childNode = arrayNode.get(i);
            String childPath = buildPath(currentPath, String.valueOf(i));

            // 递归调用
            findNodesRecursive(childNode, childPath, arrayNode, targetFieldName, targetValue, results);
        }
    }

    /**
     * 遍历JSON对象（带自定义条件）
     */
    private static void traverseObject(JsonNode objectNode, String currentPath, 
                                      List<NodePathInfo> results, String targetFieldName, 
                                      String targetValue, Predicate<JsonNode> condition) {
        
        Iterator<Map.Entry<String, JsonNode>> fields = objectNode.fields();
        while (fields.hasNext()) {
            Map.Entry<String, JsonNode> entry = fields.next();
            String fieldName = entry.getKey();
            JsonNode childNode = entry.getValue();
            String childPath = buildPath(currentPath, fieldName);

            findNodesRecursive(childNode, childPath, objectNode, targetFieldName, targetValue, results, condition);
        }
    }

    /**
     * 遍历JSON数组（带自定义条件）
     */
    private static void traverseArray(JsonNode arrayNode, String currentPath, 
                                     List<NodePathInfo> results, String targetFieldName, 
                                     String targetValue, Predicate<JsonNode> condition) {
        
        for (int i = 0; i < arrayNode.size(); i++) {
            JsonNode childNode = arrayNode.get(i);
            String childPath = buildPath(currentPath, String.valueOf(i));

            findNodesRecursive(childNode, childPath, arrayNode, targetFieldName, targetValue, results, condition);
        }
    }

    /**
     * 检查字段名匹配
     */
    private static void checkFieldNameMatch(JsonNode currentNode, String currentPath, 
                                           JsonNode parentNode, String targetFieldName, 
                                           List<NodePathInfo> results) {
        
        // 从路径中提取字段名（最后一段）
        String[] pathSegments = currentPath.split("/");
        if (pathSegments.length > 0) {
            String lastSegment = pathSegments[pathSegments.length - 1];
            if (lastSegment.equals(targetFieldName)) {
                results.add(new NodePathInfo(currentNode, currentPath, parentNode));
            }
        }
    }

    /**
     * 检查值匹配
     */
    private static void checkValueMatch(JsonNode currentNode, String currentPath, 
                                       JsonNode parentNode, String targetValue, 
                                       List<NodePathInfo> results) {
        
        if (currentNode.asText().equals(targetValue)) {
            results.add(new NodePathInfo(currentNode, currentPath, parentNode));
        }
    }

    /**
     * 构建路径
     */
    private static String buildPath(String parentPath, String segment) {
        if (parentPath.isEmpty()) {
            return segment;
        }
        return parentPath + "/" + segment;
    }

    /**
     * 节点路径信息类
     */
    public static class NodePathInfo {
        public final JsonNode node;
        public final String path;
        public final JsonNode parentNode;
        public final List<String> pathSegments;

        public NodePathInfo(JsonNode node, String path, JsonNode parentNode) {
            this.node = node;
            this.path = path;
            this.parentNode = parentNode;
            this.pathSegments = parsePathSegments(path);
        }

        private List<String> parsePathSegments(String path) {
            return Arrays.stream(path.split("/"))
                      .filter(segment -> !segment.isEmpty())
                      .collect(Collectors.toList());
        }

        /**
         * 获取父节点路径
         */
        public String getParentPath() {
            int lastSlashIndex = path.lastIndexOf('/');
            if (lastSlashIndex <= 0) {
                return "";
            }
            return path.substring(0, lastSlashIndex);
        }

        /**
         * 获取字段名（对于对象字段）
         */
        public String getFieldName() {
            if (pathSegments.isEmpty()) {
                return "";
            }
            return pathSegments.get(pathSegments.size() - 1);
        }

        /**
         * 获取索引（对于数组元素）
         */
        public Optional<Integer> getArrayIndex() {
            if (pathSegments.isEmpty()) {
                return Optional.empty();
            }
            String lastSegment = pathSegments.get(pathSegments.size() - 1);
            try {
                return Optional.of(Integer.parseInt(lastSegment));
            } catch (NumberFormatException e) {
                return Optional.empty();
            }
        }

        @Override
        public String toString() {
            String valueStr = node.isValueNode() ? node.asText() : node.getNodeType().toString();
            String parentType = parentNode != null ? parentNode.getNodeType().toString() : "ROOT";
            
            return String.format("Path: %-20s | Value: %-15s | Parent: %-8s | Type: %s",
                path, valueStr, parentType, node.getNodeType());
        }
    }
}